////////////////////////////////// Includes ///////////////////////////////////

#include "stdafx.h"
#include "PJNSMTPApp.h"
#include "PJNSMTPAppDlg.h"


///////////////////////////////// Macros / Defines ////////////////////////////

#ifndef CPJNSMTP_NOSSL
CCriticalSection* CPJNSMTPApp::m_pOpenSSLCritSections = NULL;
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


//////////////////////////////// Implementation ///////////////////////////////

BEGIN_MESSAGE_MAP(CPJNSMTPApp, CWinApp)
END_MESSAGE_MAP()

CPJNSMTPApp::CPJNSMTPApp()
{
}

CPJNSMTPApp theApp;


#ifndef CPJNSMTP_NOSSL
void __cdecl CPJNSMTPApp::OpenSSLLockingCallback(int mode, int type, const char* /*file*/, int /*line*/)
{
  AFXASSUME(m_pOpenSSLCritSections);
	if (mode & CRYPTO_LOCK)
		m_pOpenSSLCritSections[type].Lock();
	else
		m_pOpenSSLCritSections[type].Unlock();
}
#endif


BOOL CPJNSMTPApp::InitInstance()
{
  //Initialize Sockets
	if (!AfxSocketInit()) 
  {
		TRACE(_T("Failed to initialise the Winsock stack\n"));
    return FALSE;
	}

#ifndef CPJNSMTP_NOSSL
  //Standard OpenSSL initialization
  SSL_load_error_strings();
  SSL_library_init();

  //Setup SSL to work correctly in a multithreaded environment
  ASSERT(m_pOpenSSLCritSections == NULL);
  m_pOpenSSLCritSections = new CCriticalSection[CRYPTO_num_locks()];
  if (m_pOpenSSLCritSections == NULL)
  {
    //Report the error
    AfxMessageBox(_T("Failed to create SSL critical sections required for OpenSSL"));
    return FALSE;
  }
  CRYPTO_set_locking_callback(OpenSSLLockingCallback);
#endif

  //Settings will be stored in the registry
  SetRegistryKey(_T("PJ Naughter"));

  //Bring up the main dialog
	CPJNSMTPAppDlg dlg;
	m_pMainWnd = &dlg;
	dlg.DoModal();

	return FALSE;
}

int CPJNSMTPApp::ExitInstance()
{
#ifndef CPJNSMTP_NOSSL
  //Clean up OpenSSL library
  stack_st_SSL_COMP* pCOMP = SSL_COMP_get_compression_methods();
  if (pCOMP)
     sk_SSL_COMP_free(pCOMP);
  ERR_remove_state(0);
  ERR_free_strings();
  EVP_cleanup();
  CRYPTO_cleanup_all_ex_data();

  //Clean up the SSL critical sections
  if (m_pOpenSSLCritSections)
  {
    delete [] m_pOpenSSLCritSections;
    m_pOpenSSLCritSections = NULL;
  }
#endif

  //Let the base class do its thing
  return CWinApp::ExitInstance();
}
